package com.example.studytools

import android.content.Context
import android.graphics.Point
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.ScaleGestureDetector
import android.widget.RelativeLayout
import java.lang.Float.max
import kotlin.math.acos
import kotlin.math.min


private const val TAG = "TransformLayout"

class TransformLayout @JvmOverloads constructor(
    private val mContext: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : RelativeLayout(mContext, attrs, defStyleAttr) {
    private var lastX: Float = 0f
    private var lastY: Float = 0f
    private var dX: Float = 0f
    private var dY: Float = 0f
    private var scaleFactor = 1.0f // 初始缩放比例为 1.0
    private var layoutDegree = 0f
    private var oriX = 0f
    private var oriY = 0f

    //缩放监听
    private val scaleGestureDetector = ScaleGestureDetector(mContext, ScaleListener())

    //手势监听
    private val gestureDetector = GestureDetector(mContext, GestureListener())

    private var layoutSizeChange: ((Int) -> Unit)? = null


    override fun onTouchEvent(event: MotionEvent): Boolean {
        return scaleGestureDetector.onTouchEvent(event) or gestureDetector.onTouchEvent(event)
    }

    inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
        override fun onDown(e: MotionEvent): Boolean {
            lastX = e.rawX
            lastY = e.rawY
            return true
        }

        override fun onScroll(
            e1: MotionEvent,
            e2: MotionEvent,
            distanceX: Float,
            distanceY: Float
        ): Boolean {
            //获取当前实时点信息
            val rawX = e2.rawX
            val rawY = e2.rawY

            //变化量
            dX = rawX - lastX
            dY = rawY - lastY


            this@TransformLayout.translationX += dX
            this@TransformLayout.translationY += dY


            //更新最后屏幕点信息
            lastX = rawX
            lastY = rawY

            return true
        }
    }

    inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() {
        /**
         * 缩放进行中，返回值表示是否下次缩放需要重置，如果返回ture，那么detector就会重置缩放事件，如果返回false，detector会在之前的缩放上继续进行计算
         */
        override fun onScale(detector: ScaleGestureDetector): Boolean {
            scaleFactor *= detector.scaleFactor
            scaleFactor = max(0.8f, min(scaleFactor, 1.5f)) // 设置最大和最小缩放比例
            this@TransformLayout.scaleY = scaleFactor
            this@TransformLayout.scaleX = scaleFactor
            return false
        }

        /**
         * 缩放开始，返回值表示是否受理后续的缩放事件
         */
        override fun onScaleBegin(detector: ScaleGestureDetector): Boolean {
            return true
        }

        override fun onScaleEnd(detector: ScaleGestureDetector) {}
    }

    fun rotateLayout(event: MotionEvent) {
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                oriX = event.x
                oriY = event.y
                layoutDegree = rotation
            }
            MotionEvent.ACTION_MOVE -> {
                val tempRawX = event.x
                val tempRawY = event.y
                val first = Point(oriX.toInt(), oriY.toInt())
                val second = Point(tempRawX.toInt(), tempRawY.toInt())
                val cen = Point(width / 2, height / 2)
                //旋转
                val angle = angle(cen, first, second)
                layoutDegree += angle
                rotation = layoutDegree

            }
            MotionEvent.ACTION_UP -> {

            }
            else -> {}
        }
    }


    private fun angle(cen: Point, first: Point, second: Point): Float {
        val dx1: Float = (first.x - cen.x).toFloat()
        val dy1: Float = (first.y - cen.y).toFloat()
        val dx2: Float = (second.x - cen.x).toFloat()
        val dy2: Float = (second.y - cen.y).toFloat()

        // 计算三边的平方
        val ab2 =
            ((second.x - first.x) * (second.x - first.x) + (second.y - first.y) * (second.y - first.y)).toFloat()
        val oa2 = dx1 * dx1 + dy1 * dy1
        val ob2 = dx2 * dx2 + dy2 * dy2

        // 根据两向量的叉乘来判断顺逆时针
        val isClockwise =
            (first.x - cen.x) * (second.y - cen.y) - (first.y - cen.y) * (second.x - cen.x) > 0
        // 根据余弦定理计算旋转角的余弦值
        var cosDegree =
            (oa2 + ob2 - ab2) / (2 * Math.sqrt(oa2.toDouble()) * Math.sqrt(ob2.toDouble()))

        // 异常处理，因为算出来会有误差绝对值可能会超过一，所以需要处理一下
        if (cosDegree > 1) {
            cosDegree = 1.0
        } else if (cosDegree < -1) {
            cosDegree = -1.0
        }

        // 计算弧度
        val radian = acos(cosDegree)

        // 计算旋转过的角度，顺时针为正，逆时针为负
        return (if (isClockwise) Math.toDegrees(radian) else -Math.toDegrees(radian)).toFloat()
    }
}